#  -*- coding: utf-8 -*-
# @Time    : 2020/11/17 22:37
# @Author  : 韋筠曦
# @Site    : 
# @File    : 参考知识.py
# @Software: PyCharm

# -*- coding: utf-8 -*-


"""
注意包名 不要以数字开头 否则会导致 引包报错  类名也不要用数字开头

pycharm   配置pyhton 环境方法   file ---> string --->project interpreter---> 添加--->vir...---->Existing env...---> int 选项添加 exe文件
---> mske 选项前 勾选     确认  应用即可     新建项目 解释器 导入 方法: file  --> other string    和pycharm 导入方式一致
pycharm run 菜单灰色 原因是 项目解释器 未导入

from sklearn.externals import joblib  会出现 joblib 不存在 现象 最简单的方式是  将 pip3 install joblib 然后将joblib 放入sklearn.externals目录下即可


takes 3  positional arguments but 4 were given 错误   说明这个函数 缺少self这个类参数     一般 在类中声明一个函数 第一个参数必须韦self  但是给这个函数传参时 不需要给这个参数传参

(unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
错误解决方案  把路径上的 "\"改成"//"

"""

# 占位符  %s 可赋值所有的类型    %d 只能赋值为数字类型   %05d  表示可以接受的范围 不够的补零 eg 5  则得到00005   若超过范围则输入多少 就输出多少
a = 'aa'
b = 'cc'
print("a%s和b%s" % (a, b))  # aaa和bcc
# 交叉赋值
ll = 1
bb = 2

ll, bb = bb, ll
print(ll, bb)  # 2 1

# 解压赋值
tt = [1, 2, 3, 4]
a1, a2, a3, a4 = tt  # 前面变量的个数与列表元素的个数要相同
a1, _, _, a4 = tt  # _ 此处位置数据用不到 用下画线代替  打印下划线 后一个值覆盖前一个值 打印的是最后一个下划线代表的值
a1, *_, a4 = tt  # 第一个元素和最后一个元素需要其余不需要  此时若不清楚这个元素的个数则无法使用一个一个下划线表示 就用*_ 来代替不清楚的且不需要的个数
print(a1, a2, a3, a4)  # 1 2 3 4

# if 判断 可以直接写变量名  当变量名指向值 为true 或者false 此时可以直接写变量名    eg  0 none []  {}  () ''     0 none []  {} () ''指向 false
#  常量 None（N 必须大写）。和 False 不同，它不表示 0，也不表示空字符串，而表示没有值，也就是空值
# if xx:       if   elif   else 同时使用(同一级别) 一次只会在执行其中一个代码块  并且代码中可以有 多个elif  只能有一个else
#     print()
# elif yy:
#     print()
# else:
#     print()
alll = None
al = 0
a1 = []
a2 = {}
if alll:
    print("222222222")
else:
    print("22222222255555555555")

# while 循环
'''
while  条件：
    代码      条件成立 则执行代码  代码执行完 然后再去判断条件是否成立 若还成立 继续执行代码    break  立即结束本层循环   即所在的while   continue 结束当前进入下一次循环
'''
x = 1
int(x)  # 不能转化内带有小数点的 字符串eg '1.1' 不能转换
str(x)  # 转为字符串类型

# ''' '''  没有变量名时就是注释
ala = '123456'
ala[0:4]  # 左闭右开  不写默认步长为1  就是 挨着取值间隔为0
ala[0:4:2]  # 左闭右开  步长为2  就是 取值间隔为1个下标 取值
# 当步长为负数时  从右往左开始取数   当取值下边eg ala[-1]表示从右往左取得的值是6

# 成员运算符   in    与 not  in   判断元素是否在某一个整体里面
# str.splitlines([keepends])  keepends -- 在输出结果里是否保留换行符('\r', '\r\n', \n')，默认为 False，不包含换行符，如果为 True，则保留换行符
# 去除字符串首尾的空格 strip   使用内置的方法 统一采用 句点符 即 .    默认是去掉空格   要去掉什么就去在strip(去掉的符号)  eg 去掉$  .strip('$')
# 只去掉左边的lstrip()     只去掉右边的 rstrip()
test = '   kkk     '.strip()
print(test)  # kkk

# 切割方法   split() 切分出来的数据类型是一个列表    **************************************
# startswith（x）字符串是否以x开头    endswith() 以什么结尾
# 字符串的格式化 format()    1. 按位置占位  跟%s 一致
strss = 'll{}oo'.format('pp')
# 2. 按照索引占位
strsst = 'll{0}oo'.format('pp', 19, 'qq')  # 获得第一个位置值
# 3.关键字传参 指定传参
strsws = 'll{name}oo{hh}'.format(name='ll', hh='哈哈')
# 字符串拼接时 不要汇合多个数据类型  采用+ 好拼接会报错   但是可以采用%s 来操作

# 判断字符串是否是纯数字 isdigit()
pppp = "777777777777777"
print(pppp.isdigit())  # true

# list（） 内部取值 利用for 循环    字典for 时 取得值值是key

# list append（）方法 添加进去得得值只是list得一个元素

# 若要将容器类型eg list得元素 添加进另外一个 list
ll = [1, 2, 3]
lls = [4, 5, 5]
lls.extend(ll)  # 内部原理 for 循环  然后将元素一个一个 追加到尾部
print(lls)  # [4, 5, 5, 1, 2, 3]
# reverse() 列表反转
# 元组若只有一个值时 需要在值后面加，eg (a,)
print('llllll&'.strip('&'))

# 字典定义方式：
asd = {}
asdf = dict(kk='ll', yy='oo', ii='uu')
print(asdf, type(asdf))  # {'kk': 'll', 'yy': 'oo', 'ii': 'uu'} <class 'dict'>

# 列表转化为字典方式
llae = [['kk', 'll'], ['kkr', 'll'], ['kkt', 'll']]
sdfg = {}
for kk, v in llae:
    sdfg[kk] = v
    print(sdfg)  # {'kk': 'll', 'kkr': 'll', 'kkt': 'll'}
# 方式二
kkkil = dict(llae)
print(kkkil)  # {'kk': 'll', 'kkr': 'll', 'kkt': 'll'}

# 获取字典得key
kkkelo = {'kk': 'll', 'yy': 'oo', 'ii': 'uu'}
llop = kkkelo.keys()
print(llop)  # dict_keys(['kk', 'yy', 'ii'])
for lowop in llop:
    print(lowop)  # kk  yy   ii

# 获得字典的值

for lowop in kkkelo.values():
    print(lowop)  # ll  oo   uu

# 迭代元素 同属获得元素的索引
names = ['Bob', 'Alice', 'Guido']

for index, value in enumerate(names):
    print(f'{index}: {value}')

    '''
    enumerate() 迭代容器中的元素，同时通过一个计数器变量记录当前元素所对应的索引值。
    0: Bob
    1: Alice
    2: Guido
    '''
# 列表套元组
yy = kkkelo.items()
print(yy)  # dict_items([('kk', 'll'), ('yy', 'oo'), ('ii', 'uu')])  需要for 获取

# 根据 key 获得value
kkl1 = {'kk': 'll', 'yy': 'oo', 'ii': 'uu'}
kkl1['kk']  # 根据key 获取值  当kkl1['kkk'] key 不存在会报错
kkl1.get('kk')  # 获得value   kkl1.get('kkk') key 不存在返回None  若想要返回别的值  kkl1.get('kkk','没有这个key')

# 快速创建字典方法
kkkkop1 = {}
pp = kkkkop1.fromkeys(['kk', 'yy', 'ii'])
print(pp)  # {'kk': None, 'yy': None, 'ii': None}
pp1 = kkkkop1.fromkeys(['kk', 'yy', 'ii'], '哈哈')
print(pp1)  # {'kk': '哈哈', 'yy': '哈哈', 'ii': '哈哈'}
# 字典新增键值对
set00 = {'kk': 'll', 'yy': 'oo', 'ii': 'uu'}
tt = set00.setdefault('kk', '0')
print(tt)  # ll    当键存在时 不修改 并且返回key得值
print(set00)  # {'kk': 'll', 'yy': 'oo', 'ii': 'uu'}
tt4 = set00.setdefault('kkk', '0')
print(tt4)  # 0 当键不存在时 返回添加得值  并将这个键值对添加进字典
print(set00)  # {'kk': 'll', 'yy': 'oo', 'ii': 'uu', 'kkk': '0'}
# 更新字典 给字典添加新数据
inset_update1 = {'kk': 'll', 'yy': 'oo', 'ii': 'uu'}
inset_update2 = {'kk1': 'll', 'yy5': 'oo', 'ii6': 'uu'}
pop = inset_update1.update(inset_update2)
print(inset_update1)  # {'kk': 'll', 'yy': 'oo', 'ii': 'uu', 'kk1': 'll', 'yy5': 'oo', 'ii6': 'uu'}
inset_update1.update(laal="哈哈哈")
print(inset_update1)  # {'kk': 'll', 'yy': 'oo', 'ii': 'uu', 'kk1': 'll', 'yy5': 'oo', 'ii6': 'uu', 'laal': '哈哈哈'}

# 群体之间做比较，不涉及单个元素  比如关系运算 去重
# 集合
# 定义空集合  ll = ()  声明空元组  集合 每个元素为不可变类型(可哈希) 没有重复元素  无序（集合不能通过索引取值）  可变不可hash
ll = set()  # 利用集合 去重
# 求两个集合共同得部分  集合1  &  集合2
# 集合1 中存在 集合2没有   集合1-集合2
# 求两个集合独有得部分    集合1 ^ 集合2
# 集合1 > 集合2   集合1 >= 集合2  集合1是否包含集合2     集合1=集合2 集合1是否等与集合二

# python  数据类型    int  float   str  tuple bool     可变 list  dict  set   容器类型：  字典  元组  集合 列表    集合输出也是一个{内容}

# 编码与解码

lsd = '呵呵'
ret_lsd1 = lsd.encode('utf-8')
print(ret_lsd1)  # b'\xe5\x91\xb5\xe5\x91\xb5'
ret_lsd2 = ret_lsd1.decode('utf-8')
print(ret_lsd2)  # 呵呵

# 字符串防转义 方法 eg  jj = r'hahahhahahah'
# jj = r'hahahhahahah\n'
# windows 操作方式是jbk

# 文件操作方法  此种方式不用关闭文件 f.close()  文件读取得结果是一个list   ********** 注意当文件以r模式打开时 文件若不存在 则直接报错***************
with open(r'路径', 'r',
          encoding='utf-8') as f:  # ,encoding='编码格式'   编码错误是使用这个  ,mode='文件操作方式' r 只读 w 只写  a 追加  默认rt 文件读取t是文件默认为t  rb 读取二进制文件
    f.read()  # 一次性将文件全部读出  但是注意这种方式文件过大时 容易导致内存泄露   读取得文件是一行一行得形式
    f.readable()  # 是否可读
    f.writable()  # 是否可写
    f.readline()  # 只读取文件一行
    f.readlines()  # 返回的是一个列表

    # 推荐使用
    for low in f:
        a = low  # 一行一行得读取
# 一次打开多个文件
with open(r'路径') as f, \
        open(r'路径') as f1:  # ,encoding='编码格式'   编码错误是使用这个
    f.read()
    f1.read()
# 文件监控
with open(r'test01.txt', 'rb') as f:
    # 先将光标移动到文件末尾
    f.seek(0, 2)
while True:
    res = f.readline()
    # 查看光标移动了多少位 bytes
    # print(f.tell())
    if res:
        print("新增的文件内容:%s" % res.decode('utf-8'))
        # 说明有人操作当前文件
    # else:
    #     # 说明文件没有被任何人操作
    #     print('暂无其他人操作该文件')

#  *********************** 截断文件******************
with open(r'路径', 'a', encoding='utf-8') as f:  # 注意utf-8 一个汉字三个字节

    f.truncate(6)  # 保留字节得得长度 整型  次处意思是 保留0~6得字节其余都删除

# 文件修改方式2
# 创建一个新文件
# 循环读取老文件内容到内存进行修改  将修改好的内容写到新文件中
# 将老文件删除  将新文件的名字改成老文件名
import os

with open(r'test02.txt', 'r', encoding='utf-8') as read_f, \
        open(r'test02.swap', 'a', encoding='utf-8') as write_f:
    for line in read_f:
        new_line = line.replace('需要替换得内容', '替换得内容')
        write_f.write(new_line)
os.remove('test02.txt')
os.rename('test02.swap', 'test02.txt')

"""
优点:内存中始终只有一行内容 不占内存
缺点:再某一时刻硬盘上会同时存在两个文件
"""

# ************************************** return  ***************************************
# return 不仅可以返回值还能直接结束函数  return 后什么都不写 返会 None  跟 return None 效果一样
# return 返回多个值  return a,b,.....     得到得是（a,b,....） 返回得为元组    ******************************
# python 中所有的函数 都有返回值 不写return 默认返回None

'''
名称空间：  存放变量名与变量值绑定关系得地方   名称空间分为 全局名称空间 局部名称空间  内置名称空间
内置名称空间： python解释器提前定义好得名字（已经存放在内置名称空间中）

作用域：
全局作用域： 全局有效
局部作用域：局部有效

局部修改 全局变量
ll=1
def lll():
  global ll  修改全局变量
  ll = 666
print(ll) # 666

局部修改局部
******************************************************
def pp():
 jj = 1
 def kk():
  nonlocal jj    # 修改多个 使用,
  jj=3
 print(jj) # 3

闭包函数: 闭：定义在函数内部得函数   包：内部函数引用外部函数作用域的名字
**************************************** 给函数体传参方式  1 传递参数  2 利用闭包函数
eg :
def uu():    # 注意这种方式 可以看成 给函数体传参
 oo=1
 def kk():
  print(oo)
 return kk
print(uu()) # 1
 开放封闭原则
 开放： 对扩展开放   封闭 对修改封闭     注意： 不改变源代码 不改变被修饰对象调用方式

'''
AA = ['SSS', 'LL']
CC = ''
for LOW in AA:
    CC = LOW
print(CC)


def aas():
    a = 1
    b = 2

    return a, b


kk, yy = aas()

# 判断key  是否在字典中的方法
d = {'name': 2, 'age': 10, 'Tel': 110}
print('name' and 'age' and 'Tel' in d.keys())  # true

'''
 函数中有yield 关键字  此时 函数调用时候加括号时 函数体的内容 并不会执行  
  eg:
  def a():
    print(444)
    yield 222

  a()  此时不会打印444  注意此时这个 是将 函数初始化 为一个生成器   生成器的本之就是迭代器   aa=a()  此时就可以迭代这个函数   aa.__next__() 
     yield 后面跟着的 就是调用这个迭代器返回的值   yield 后面的值 可以是多个 以元组的方式返回  yield 在第一次待用这个迭代器时 会执行到这个yield 
     第二次调用这个迭代器时 会从第一次yield 后开始执行代码


   python 中使用正则表达式时 需要使用re模块
'''

'''
range()
xxx takes 1 positional argument but 2 were given 错误  类方法 第一个参数 必须是 self  xxx 这个方法 并不是


L = [75, 98, 59, 81, 66, 43, 69, 85]
sum = 0.0
n = []
for x in L:   # 方式一
     if x < 60:
         continue
    sum = sum + x
    n.append(x)
 print(n)

# 方式二
for xx in L:
    if xx < 60:
        n.append(xx)
    else:   # 注意  else 中若只有一个 continue 时 条件不成立会直接跳入下一次循环 这种方式 可以将 else 去掉 这个是多余代码  因为不成立 会直接跳入下一次循环
        print(1111)
        continue

方式二 简化：
for xx in L:
    if xx < 60:
        n.append(xx)


'''
'''
# 有序字典  添加顺序与输出顺序一致：

from  collections  import OrderedDict

orde_dric=OrderedDict()

orde_dric['A']=1
orde_dric['b']=1
orde_dric['c']=1

for low in orde_dric:
    print(low)   
# A
# b
# c
'''
'''
# 与操作系统打交道：
import os

os.path.dirname(目录路径)
os.mkdir(文件夹名称) 创建文件夹
os.path.exists(r'文件路径or文件夹') 判断文件或文件夹是否存在
os.path.isfile(r'文件路径') 只能判断文件是否存在 存在 则 true
os.rmdir(r'空文件夹路径') 只能删除空文件夹
'''
'''
# 与python 解释器打交道
import sys
sys.path.append() # 将某个路径添加到系统变量中去
sys.platform() # 查看当前系统版本
sys.version() # 查看当前python 解释器版本
'''

'''
序列化：其他数据类型转换为字符串
序列： 字符串
写入文件的数据必须是字符串
基于网络传输的数据必须是二进制

字典  是单引号
序列化
反序列化
json 格式的字符串 必须是双引号
dumps ：序列化 将其他数据类型 转为json
loads : 反序列化 
带s的转换  不带s的需要传入一个文件对象
dump:  序列化  文件对象  一般是将其他数据类型 转为json 然后保存到文件
load: 反序列化 文件对象
注意字典中有中文 出现转码问题解决方案

import json
aa={'dd':'哈哈'}
json.dumps(aa,ensure_ascii=False)  # ensure_ascii 中文是否转码 false 不转码
'''
import json

aa = {'dd': '哈哈'}
json.dumps()

'''
# 集合字典列表 合并
a = []
b = [4,5,6]
da = a + b
print(da)   # [4,5,6]
al=[1,2,3]
bl = [4,5,6]
dl =al+bl
print(dl) # [1,2,3,4,5,6]
pp = {'a':[1,11,111], 'b': [14,114,1114], 'c':[21,211,1211]} 
uu = {'a':[41,443,4424],'b':[14,44,444],'c':[4,44,444]}
hh=pp.get('a')+uu.get('a')
print(hh) # [1,11,111,41,443,4424]

# 注意  两个字典的key 不能相同 否则会出现覆盖
A = {'a': [1,11,111], 'b': 22}
B = {'c': [14,44,444], 'd': 13}
#update() 把字典B的键/值对更新到A里
A.update(B)
print(A) # {'a': [1,11,111], 'b': 22,'c': [14,44,444], 'd': 13}
pp={}
pp['aa']=A
print(pp) # {'aa':{'a': [1,11,111], 'b': 22,'c': [14,44,444], 'd': 13}}
KKx = [{'a': [1,11,111], 'b': 22}]
KK = [{'a': [1,13,14], 'b': 32}]
BB = [ {'c': [14,44,444], 'd': 13},{'c': [14,44,444], 'd': 13},{'c': [14,44,444], 'd': 13}]
PPPP= KK + BB + KKx
# KEY 相同 值覆盖
print(PPPP)  #[{'a': [1, 13, 14], 'b': 32}, {'c': [14, 44, 444], 'd': 13}, {'c': [14, 44, 444], 'd': 13}, {'c': [14, 44, 444], 'd': 13}, {'a': [1, 11, 111], 'b': 22}]


fg = {'c': [14,44,444], 'd': 13}
print(fg.get("c")) # [14, 44, 444]
'''
# todo 条件表达式  先对中间条件求值 若是true 则会if 左边的数据处理  否则就进行else数据的处理
''' 
if a < b :
    i=3
else:
    i=4
代码简化：
i=3 if a<b else 4
'''
# todo 异常处理 else 必须跟在except 后面  try 没有异常 就会执行else

'''
try:

except   xxx    :

else:

'''














